import { Handler } from "$fresh/server.ts";
import { deleteCookie, getCookies } from "$std/http/mod.ts";
import { ConsoleHandler, getLogger, setup } from "logger";
import { getResumeAuthingSDK } from "~/tools/sdk/authing.ts";
import dayjs from "dayjs";
import { AuthenticationClient } from "authing";

export type AdminState = {
  user: Awaited<
    ReturnType<AuthenticationClient["getProfile"]>
  >["data"];
};

const witeList = ["/admin/login"];

setup({
  handlers: {
    default: new ConsoleHandler("INFO", {
      formatter: (record) => {
        return `admin middleware: ${
          dayjs(record.datetime).format("YYYY-MM-DD HH:mm:ss")
        } [${record.levelName}] ${record.msg}`;
      },
    }),
  },
});
const dl = getLogger();
export const handler: Handler<unknown, AdminState> = async (req, ctx) => {
  const cookies = getCookies(req.headers);
  const jwt = cookies["jwt"];
  dl.info(`${req.method}:${ctx.url.pathname}`);

  if (witeList.includes(ctx.url.pathname)) {
    dl.info(ctx.url.pathname + ":白名单访问");
    return ctx.next();
  }

  // 没有jwt,不予访问
  if (!jwt) {
    const sdk = getResumeAuthingSDK();
    const result = sdk.buildAuthorizeUrl({
      redirectUri: Deno.env.get("location") + "/admin/login",
      responseType: "code",
      scope: "profile openid",
    });
    dl.info(
      "/admin:检测到没有access token,重定向登陆",
      result.url,
    );
    return new Response(null, {
      status: 302,
      headers: { Location: result.url },
    });
  }

  const sdk = getResumeAuthingSDK();

  const { active } = await sdk.introspectToken(jwt);
  if (!active) {
    const resp = new Response(
      `通过access token已失效,请重新登陆`,
      {
        status: 400,
      },
    );
    deleteCookie(resp.headers, "jwt", { path: "/admin" });
    return resp;
  }
  sdk.setAccessToken(jwt);
  return sdk.getProfile({ withCustomData: true })
    .then((user) => {
      dl.info("通过access token获得用户信息成功");
      ctx.state = {
        user: user.data,
      };
      return ctx.next();
    }, async (e) => {
      dl.error(e);
      const resp = new Response(
        `通过access token已失效,请重新登陆`,
        {
          status: 400,
        },
      );
      deleteCookie(resp.headers, "jwt", { path: "/admin" });
      await sdk.revokeToken(jwt);
      dl.info(`revokeToken ${jwt} 成功`);
      deleteCookie(resp.headers, "jwt", { path: "/admin" });
      return resp;
    });
};
